package com.xyq.fs.views;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;


import org.apache.lucene.document.Document;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;

import com.xyq.fs.constants.FieldConstant;

import com.xyq.fs.entity.MyFile;

import com.xyq.fs.search.MySearch;
import com.xyq.fs.search.SearchBody;
import com.xyq.fs.util.MyFilesUtil;

import com.xyq.fs.views.WindowsGo;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.InvalidationListener;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;

import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;

import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TableColumn.CellDataFeatures;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
import javafx.util.Callback;

/**
 * 查询结果窗口
 * 
 * @author xyq
 *
 */
public class WindowsB extends Application {

	private Group root = new Group();
	private Scene scene = new Scene(root, 682, 560);
	private Stage stage;

	private SearchBody body;

	public WindowsB(SearchBody body) {

		this.body = body;

	}

	private TableView<MyData> tableView = new TableView<MyData>();
	private ObservableList<MyData> dataa = FXCollections.observableArrayList();
	private VBox vBox = new VBox();
	private HBox hBox2 = new HBox();
	private TextFlow tff = new TextFlow();
	private Text t1 = new Text();

	private Button btnNext = new Button("下一页");
	private Button btnPre = new Button("上一页");
	private Button BtnC = new Button("当前页: 1");
	private Text currentPageNumText = new Text("当前页:  ");

	// 绑定文件名
	private TableColumn<MyData, TextFlow> nameCol = new TableColumn<MyData, TextFlow>("文件名");
	// 绑定文件预览按钮
	private TableColumn<MyData, Button> seeCol = new TableColumn<MyData, Button>("内容预览");
	// 绑定访问目录按钮
	private TableColumn<MyData, Button> dirCol = new TableColumn<MyData, Button>("访问目录");
	// 绑定复制文件按钮
	private TableColumn<MyData, Button> cpoyCol = new TableColumn<MyData, Button>("复制文件");

	private static String btnStr = WindowsB.class.getResource("WindowsB.css").toExternalForm();

	/**
	 * 构建一个查询参数对象
	 */

	// 最大页数
	private int maxPageNum = 0;

	// 分页标记
	private Map<Integer, ScoreDoc> fenyeMap = new HashMap<>();

	// 缓存对象
	private Map<Integer, MyFile> cacheMyFile = new HashMap<Integer, MyFile>();
	private Map<Integer, MyData> myDataMap = new HashMap<Integer, MyData>();
	private Map<Document, Path> docMap = new HashMap<Document, Path>();
	private Map<String, TextFlow> tfMap = new HashMap<String, TextFlow>();
	private static Font hFont = Font.font("微软雅黑", FontWeight.BOLD, 14);
	private static Font YH = new Font("微软雅黑", 15);
	private static String YHSTR = "-fx-font-family: '微软雅黑';";
	private WindowsC WC;

	private Stage wcState;

	{
		Platform.runLater(() -> {
			WC = new WindowsC();
			wcState = new Stage();
			WC.start(wcState);
		});
	}

	private Map<String, WindowsC> cmap = new HashMap<String, WindowsC>();
	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private static Runtime RT = Runtime.getRuntime();

	private int pageNum = 1;


	public int getPageNum() {
		return pageNum;
	}

	public void setPageNum(int pageNum) {
		this.pageNum = pageNum;
	}

	private Query query;

	public WindowsB(SearchBody body, Query query) {

		this.body = body;
		this.query = query;

	}

	private Stage primaryStage;

	@SuppressWarnings("unchecked")
	@Override
	public void start(Stage primaryStage) throws Exception {

		BtnC.setId("btnc");
		btnPre.setId("btna");
		btnNext.setId("btna");

		root.getChildren().add(new ImageView(WindowsGo.imageA));
		root.getChildren().add(vBox);
		scene.setCursor(WindowsGo.Mouse);
		stage = new Stage();
		stage.setScene(scene);

		vBox.getChildren().addAll(hBox2, tff, tableView);
		vBox.setMinHeight(500);
		vBox.setSpacing(20);
		hBox2.setPadding(new Insets(30, 10, -10, 23));
		hBox2.getChildren().addAll(btnPre, new Text("    "), btnNext, BtnC);
		tff = new TextFlow(t1);
		tff.setPadding(new Insets(10.5, 17.5, 0, 23));
		vBox.getChildren().set(1, tff);
		t1.setId("scanTs");
		t1.setFont(YH);
		t1.setFill(Color.valueOf("#CDC5BF"));

		btnNext.getStylesheets().add(btnStr);
		btnPre.getStylesheets().add(btnStr);
		btnNext.setPrefSize(85, 31);
		btnPre.setPrefSize(85, 31);
		BtnC.getStylesheets().add(btnStr);
		BtnC.setPrefSize(180, 31);

		tableView.getColumns().addAll(nameCol, seeCol, dirCol, cpoyCol);
		tableView.setItems(dataa);

		tableView.setStyle("-fx-opacity: 0.74;");
		tableView.setStyle(YHSTR);
		tableView.getStylesheets().add(btnStr);
		tableView.setMinHeight(428);
		tableView.setTranslateX(0);

		nameCol.setStyle(YHSTR);
		nameCol.setMinWidth(479);
		nameCol.setCellValueFactory(new Callback<CellDataFeatures<MyData, TextFlow>, ObservableValue<TextFlow>>() {
			public ObservableValue<TextFlow> call(CellDataFeatures<MyData, TextFlow> p) {
				return p.getValue().getFileName();
			}
		});

		seeCol.setStyle(YHSTR);
		seeCol.setMaxWidth(72);
		seeCol.setCellValueFactory(new Callback<CellDataFeatures<MyData, Button>, ObservableValue<Button>>() {
			public ObservableValue<Button> call(CellDataFeatures<MyData, Button> p) {
				return p.getValue().getSeeBtn();
			}
		});

		dirCol.setMaxWidth(72);
		dirCol.setStyle(YHSTR);
		dirCol.setCellValueFactory(new Callback<CellDataFeatures<MyData, Button>, ObservableValue<Button>>() {
			public ObservableValue<Button> call(CellDataFeatures<MyData, Button> p) {
				return p.getValue().getDirBtn();
			}
		});

		cpoyCol.setMaxWidth(72);
		cpoyCol.setStyle(YHSTR);
		cpoyCol.setCellValueFactory(new Callback<CellDataFeatures<MyData, Button>, ObservableValue<Button>>() {
			public ObservableValue<Button> call(CellDataFeatures<MyData, Button> p) {
				return p.getValue().getCopyBtn();
			}
		});

		currentPageNumText.setId("txt");
		currentPageNumText.setFill(Color.WHITE);
		currentPageNumText.setFont(YH);
		currentPageNumText.setStyle("-fx-text-alignment:center;");

		this.primaryStage = primaryStage;
		/**
		 * 第一次查询
		 */

		MySearch.PUBLICKEY = body.getSearchKeys();
		MyFile my = cacheMyFile.get(pageNum);
		if (my == null || WindowsGo.SLEEP_NOW == 1) {
			my = MySearch.search(query, fenyeMap.get(pageNum));
			// 加入缓存
			cacheMyFile.put(pageNum, my);
		}

		for (int i = 0; i < my.getDocList().size(); i++) {
			Document doc = my.getDocList().get(i);
			MyData md = new MyData(doc);
			dataa.add(md);
			myDataMap.put(i, md);
		}
	
		fenyeMap.put(pageNum + 1, my.getAfterScoreDoc());
		maxPageNum = my.getMaxPageNum();
		t1.setText("关键词:  \"" + body.getSearchKey() + "\"  共查询到了" + (my.getTotalResultNum()) + "条相关记录,每页显示5条。");
		BtnC.setText("当前页: " + pageNum + "/" + maxPageNum);
		primaryStage.setScene(scene);
		getNextPage();


		// 在scene中修改光标

		/**
		 * 点击上一页按钮
		 */
		btnPre.setOnAction(new EventHandler<ActionEvent>() {

			@Override
			public void handle(ActionEvent t) {

				MySearch.PUBLICKEY = body.getSearchKeys();
				if (pageNum > 1) {
					pageNum--;
					MyFile my = cacheMyFile.get(pageNum);
					Document doc;
					for (int i = 0; i < my.getDocList().size(); i++) {
						doc = my.getDocList().get(i);
						MyData md = myDataMap.get(i);
						myDataMap.put(i, md);
						dataa.set(i, md);
						md.setDoc(doc);
					}
					BtnC.setText("当前页: " + pageNum + "/" + maxPageNum);
					doc = null;
				} else {
					MyAlert.alertError("已经是第一页了!!!");
				}
			}
		});

		/**
		 * 点击下一页按钮
		 */
		btnNext.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent t) {

				MySearch.PUBLICKEY = body.getSearchKeys();
				if (pageNum < maxPageNum) {
					pageNum++;
					MyFile my = cacheMyFile.get(pageNum);
					if (my == null) {
						my = MySearch.search(query, fenyeMap.get(pageNum));
						cacheMyFile.put(pageNum, my);
					}
					;
					for (int i = 0; i < my.getDocList().size(); i++) {
						Document doc = my.getDocList().get(i);
						MyData md = myDataMap.get(i);
						dataa.set(i, md);
						md.setDoc(doc);
					}
					// 加入缓存
					fenyeMap.put(pageNum + 1, my.getAfterScoreDoc());
					getNextPage();
					BtnC.setText("当前页: " + pageNum + "/" + maxPageNum);

				} else {
					MyAlert.alertError("已经是最后一页了!!!");
				}
			}
		});
	}

	public void show() {
		primaryStage.show();
	}

	private void getNextPage() {

		new Thread(() -> {
			int next = pageNum + 1;
			MyFile my2 = cacheMyFile.get(next);
			if (my2 == null) {
				// 缓存下一页
				MyFile my3 = MySearch.search(query, fenyeMap.get(next));
				cacheMyFile.put(next, my3);
				fenyeMap.put(next + 1, my3.getAfterScoreDoc());
			}
		}).start();
	}

	/**
	 * 页面绑定类
	 * 
	 * @author xyq
	 *
	 */
	private class MyData {

		private TextFlow tf;
		private ObservableValue<Button> dirBtn;
		private ObservableValue<Button> copyBtn;
		private ObservableValue<Button> seeBtn;
		private ObservableValue<TextFlow> fileName;

		private Button btn = new Button("查看目录");
		private Button btn2 = new Button("内容预览");
		private Button btn3 = new Button("复制文件");

		{
			btn.setId("teshu");
			btn2.setId("teshu");
			btn3.setId("teshu");
		}

		private Document docc;
		private Path pathNow;
		private String cmdStr;

		public void setDoc(Document doc) {

			init(doc);
		}

		private void init(Document doc) {

			docc = doc;
			Path path2 = docMap.get(docc);
			if (path2 == null) {
				path2 = Paths.get(docc.get(FieldConstant.FILE_PATH));
				docMap.put(docc, path2);
			}
			pathNow = path2;
			String str = pathNow + body.getSearchKey();
			TextFlow tf2 = tfMap.get(str);
			if (tf2 == null) {
				tf2 = high2(docc.get(FieldConstant.FILE_NAME), body.getSearchKeys(), pathNow.getParent().toString(),
						doc.get(FieldConstant.FILE_UPDATE_TIME));
				tfMap.put(str, tf2);
				tf2.setPrefHeight(68);
			}
			this.tf = tf2;
			cmdStr = "explorer /select, " + pathNow;
		}

		public MyData(Document doc) {

			init(doc);
			// 行高

			this.fileName = new ObservableValue<TextFlow>() {

				@Override
				public void removeListener(InvalidationListener arg0) {
				}

				@Override
				public void addListener(InvalidationListener arg0) {
				}

				@Override
				public void removeListener(ChangeListener<? super TextFlow> listener) {
				}

				@Override
				public TextFlow getValue() {

					return tf;
				}

				@Override
				public void addListener(ChangeListener<? super TextFlow> listener) {
				}
			};

			this.dirBtn = new ObservableValue<Button>() {
				@Override
				public void addListener(InvalidationListener listener) {
				}

				@Override
				public void removeListener(InvalidationListener listener) {
				}

				@Override
				public void addListener(ChangeListener<? super Button> listener) {
				}

				@Override
				public void removeListener(ChangeListener<? super Button> listener) {
				}

				@Override
				public Button getValue() {

					btn.setOnAction(new EventHandler<ActionEvent>() {
						@Override
						public void handle(ActionEvent event) {

							openDir(pathNow);
						}
					});
					return btn;
				}
			};

			this.seeBtn = new ObservableValue<Button>() {

				@Override
				public void addListener(InvalidationListener listener) {
				}

				@Override
				public void removeListener(InvalidationListener listener) {
				}

				@Override
				public void addListener(ChangeListener<? super Button> listener) {
				}

				@Override
				public void removeListener(ChangeListener<? super Button> listener) {
				}

				@Override
				public Button getValue() {

					btn2.setOnAction(new EventHandler<ActionEvent>() {
						@Override
						public void handle(ActionEvent event) {

							if (!Files.exists(pathNow)) {
								MyAlert.alertError("抱歉,文件未找到!!!");
							} else {
								WindowsC wcc = cmap.get(pathNow.toString() + body.getSearchKey());
								if (wcc != null) {
									wcc.show2();
								} else {
									WC.setPath(pathNow);
									WC.show(body.getSearchKeys());
									cmap.put(pathNow.toString() + body.getSearchKey(), WC);
									WC = new WindowsC();
									wcState = new Stage();
									WC.start(wcState);
								}
							}
						}
					});
					return btn2;
				}
			};

			this.copyBtn = new ObservableValue<Button>() {
				@Override
				public void removeListener(InvalidationListener listener) {
				}

				@Override
				public void addListener(InvalidationListener listener) {
				}

				@Override
				public void removeListener(ChangeListener<? super Button> listener) {
				}

				@Override
				public Button getValue() {

					btn3.setOnAction(new EventHandler<ActionEvent>() {
						@Override
						public void handle(ActionEvent event) {

							// 0表示原来的，1表示现在的，2表示都没有

							if (!Files.exists(pathNow)) {
								MyAlert.alertError("文件未找到");
							} else {
								try {
									new MyFilesUtil().copeFile((pathNow).toString());
									MyAlert.alert("文件已复制");
									// JOptionPane.showMessageDialog(null,
									// "复制文件成功");
								} catch (Exception e) {
									MyAlert.alertError("文件复制失败");
								}
							}
						}
					});
					return btn3;
				}

				@Override
				public void addListener(ChangeListener<? super Button> listener) {

				}
			};

		}

		public ObservableValue<TextFlow> getFileName() {

			return fileName;
		}

		public ObservableValue<Button> getDirBtn() {
			return dirBtn;
		}

		public ObservableValue<Button> getCopyBtn() {
			return copyBtn;
		}

		public ObservableValue<Button> getSeeBtn() {
			return seeBtn;
		}

		private TextFlow high2(String str, String[] keys, String path, String updateTime) {

			List<Text> txtList = new ArrayList<>();
			Text t;
			Set<Character> set = new HashSet<>();
			for (String key : keys) {
				// 关键词转化为小写
				for (int i = 0; i < key.length(); i++)
					set.add(key.charAt(i));
			}
			// 标红的开头和结尾
			int s = -1;
			// 普通的开头和结尾
			int ss = -1;

			String str2 = str.toLowerCase();
			for (int i = 0; i < str.length(); i++) {
				char c = str2.charAt(i);
				if (set.contains(c)) {
					// 如果是开头
					if (s == -1) {
						s = i;
					}
					if (ss != -1) {
						t = new Text(str.substring(ss, i));
						t.setFont(hFont);
						ss = -1;
						txtList.add(t);
					}
				} else {
					// 如果此时有开头结尾，就要把红的装起来
					if (s != -1) {
						t = new Text(str.substring(s, i));
						t.setFill(Color.RED);
						t.setFont(hFont);
						s = -1;
						txtList.add(t);
					}
					if (ss == -1) {
						ss = i;
					}
				}
			}
			if (ss != -1) {
				t = new Text(str.substring(ss));
				t.setFont(hFont);
				txtList.add(t);
			}
			if (s != -1) {
				t = new Text(str.substring(s));
				t.setFont(hFont);
				t.setFill(Color.RED);
				txtList.add(t);
			}

			if (path.toString().length() < 70) {
				List<Text> txtList2 = new ArrayList<>();
				txtList2.add(new Text("\n"));
				txtList2.addAll(txtList);
				txtList = txtList2;
			}
			t = new Text("\n" + path);
			txtList.add(t);

			t = new Text("\n" + "(" + sdf.format(new Date(Long.parseLong(updateTime))) + ")");
			txtList.add(t);
			Text[] tar = {};
			str2 = null;
			str = null;
			TextFlow tf = new TextFlow(txtList.toArray(tar));
			return tf;
		}

		private void openDir(Path path) {

			Platform.runLater(() -> {

				if (!Files.exists(path)) {
					MyAlert.alertError("抱歉,文件未找到!!!");
				} else {
					try {
						RT.exec(cmdStr);
					} catch (Exception e1) {
						e1.printStackTrace();
					}

				}
			});
		}
	}
	/**
	 * 高亮算法
	 * 
	 * @param str
	 * @param key
	 * @return
	 */

}
